package com.fy.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.fy.client.Neo4jLink;
import com.fy.dao.CarRepository;
import com.fy.dao.PersonRepository;
import com.fy.dao.ProductRepository;
import com.fy.entity.CarEntity;
import com.fy.entity.Person;
import com.fy.entity.ProductEntity;
import jakarta.annotation.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName PersonController
 * @author: maliang
 * @Description 人员
 * @date 2023/3/30 13:50
 * @Version 1.0版本
 */
@RestController
@RequestMapping("person")
public class PersonController {

    @Resource
    private PersonRepository repository;

    @Resource
    private ProductRepository productRepository;

    @Resource
    private CarRepository carRepository;

    @Resource
    private Neo4jLink neo4jLink;

    @PostMapping
    public String add(@RequestBody List<Person> personList) {
        repository.saveAll(personList);
        return "success";
    }

    @PostMapping("addProduct")
    public String saveHave(Long personId, Long productId) {
        Optional<Person> person = repository.findById(personId);
        person.ifPresent(e -> {
            Optional<ProductEntity> product = productRepository.findById(productId);
            product.ifPresent(p -> {
                e.getProductEntityList().add(p);
                repository.save(e);
            });
        });
        return "success";
    }

    @DeleteMapping("removeProduct")
    public String removeProduct(Long personId, Long productId) {
        String dele = "MATCH (p:person)-[h:have]->(p1:product) where id(p) = $personId and id(p1) = $productId detach delete h";
        HashMap<String, Object> objectObjectHashMap = MapUtil.newHashMap();
        objectObjectHashMap.put("personId", personId);
        objectObjectHashMap.put("productId", productId);
        neo4jLink.write(dele, objectObjectHashMap);
        return "success";
    }


    @PostMapping("addCar")
    public String addCar(Long personId, Long carId) {
        Optional<Person> person = repository.findById(personId);
        person.ifPresent(e -> {
            Optional<CarEntity> car = carRepository.findById(carId);
            car.ifPresent(c -> {
                e.getCars().add(c);
                repository.save(e);
            });
        });
        return "success";
    }

    @DeleteMapping("remoteCar")
    public String remoteCar(Long personId, Long carId) {
        Optional<Person> person = repository.findById(personId);
        person.ifPresent(e -> {
            List<CarEntity> cars = e.getCars();
            List<CarEntity> collect = cars.stream().filter(c -> !c.getId().equals(carId)).collect(Collectors.toList());
            e.setCars(collect);
            repository.save(e);
        });
        return "success";
    }

    @PostMapping("addKinsfolk")
    public String addKinsfolk(Long personId, Long kinsfolkId) {
        Optional<Person> person = repository.findById(personId);
        person.ifPresent(e -> {
            Optional<Person> kinsfolk = repository.findById(kinsfolkId);
            kinsfolk.ifPresent(c -> {
                e.getKinsfolkShips().add(c);
                repository.save(e);
            });
        });
        return "success";
    }

    @GetMapping("list")
    public List<Person> list() {
        List<Person> all = repository.getAll();
        for (Person person : all) {
            Long id = person.getId();
            person.setProductEntityList(productRepository.getByPersonId(id));
            person.setCars(carRepository.getByPersonId(id));
            person.setKinsfolkShips(repository.getKinsfolkById(id));
        }
        return all;
    }

    @GetMapping("page")
    public Page<Person> page(String ids, @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize) {
        pageNum = pageNum - 1;
        List<Long> collect = StrUtil.split(ids, ',').stream().map(Long::parseLong).collect(Collectors.toList());
        Pageable pageable = PageRequest.of(pageNum, pageSize);
        Map<String, Object> paramMap = Collections.singletonMap("ids", collect);
//        Page<Person> page = repository.findByIds(collect, pageable);
        List<Person> all = neo4jLink.queryList("MATCH(n:person) WHERE id(n) in $ids RETURN n", paramMap, Person.class);
        List<Person> content = CollUtil.newArrayList(all);
        long total = neo4jLink.getCount("MATCH(n:person) WHERE id(n) in $ids RETURN count(*)", paramMap);
        Page<Person> page = new PageImpl<>(content, pageable, total);
        for (Person person : page) {
            Long id = person.getId();
            Map<String, Object> idMap = MapUtil.of("id", id);
            List<ProductEntity> productEntity = neo4jLink.queryList("MATCH (p:person)-[:have]->(n:product) WHERE p.id = $id RETURN n", idMap, ProductEntity.class);
            List<CarEntity> carEntityList = neo4jLink.queryList("MATCH (p:person)-[:have]->(n:car) WHERE id(p) = $id RETURN n", idMap, CarEntity.class);
            List<Person> personList = neo4jLink.queryList("MATCH(n:person)-[:kinsfolk]->(m:person) where id(n) = $id RETURN m", idMap, Person.class);
            person.setCars(carEntityList);
            person.setKinsfolkShips(personList);
            person.setProductEntityList(productEntity);
        }
        return page;
    }

    @GetMapping("findById")
    public Person findById(Long id) {
        return repository.getById(id);
    }


}
